﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ОбработчикиСобытий

Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
	
	Если ВидФормы = "ФормаЗаписи" Тогда
		
		СтандартнаяОбработка = Ложь;
		
		Если Параметры.Ключ.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов Тогда
			
			ВыбраннаяФорма = "РегистрСведений.ПравилаДляОбменаДанными.Форма.ПравилаКонвертацииОбъектов";
			
		ИначеЕсли Параметры.Ключ.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов Тогда
			
			ВыбраннаяФорма = "РегистрСведений.ПравилаДляОбменаДанными.Форма.ПравилаРегистрацииОбъектов";
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти
	
#Область СлужебныйПрограммныйИнтерфейс

Функция ПравилаКонвертацииСовместимыСТекущейВерсией(ИмяПланаОбмена, ОписаниеОшибки, ДанныеОПравилах) Экспорт
	
	Если Не ОбменДаннымиСервер.ЗначениеНастройкиПланаОбмена(ИмяПланаОбмена, "ПредупреждатьОНесоответствииВерсийПравилОбмена") Тогда
		Возврат Истина;
	КонецЕсли;
	
	ИмяКонфигурацииИзПравил = ВРег(ДанныеОПравилах.ИмяКонфигурации);
	ИмяКонфигурацииИнформационнойБазы = СтрЗаменить(ВРег(Метаданные.Имя), "БАЗОВАЯ", "");
	Если ИмяКонфигурацииИзПравил <> ИмяКонфигурацииИнформационнойБазы Тогда
		
		ОписаниеОшибки = Новый Структура;
		ОписаниеОшибки.Вставить("ВидОшибки", "НекорректнаяКонфигурация");
		ОписаниеОшибки.Вставить("Картинка",  БиблиотекаКартинок.Ошибка32);
		
		ОписаниеОшибки.Вставить("ТекстОшибки",
			НСтр("ru = 'Правила не могут быть загружены, так как они предназначены для программы ""%1"".
			|Следует использовать правила из конфигурации или загрузить корректный комплект правил из файла.'"));
		ОписаниеОшибки.ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ОписаниеОшибки.ТекстОшибки,
			ДанныеОПравилах.СинонимКонфигурацииВПравилах);
		
		Возврат Ложь;
		
	КонецЕсли;
	
	ВерсияВПравилах    = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(ДанныеОПравилах.ВерсияКонфигурации);
	ВерсияКонфигурации = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(Метаданные.Версия);
	РезультатСравнения = ОбщегоНазначенияКлиентСервер.СравнитьВерсииБезНомераСборки(ВерсияВПравилах, ВерсияКонфигурации);
	
	Если РезультатСравнения <> 0 Тогда
		
		Если РезультатСравнения < 0 Тогда
			
			ТекстОшибки = НСтр("ru = 'Синхронизация данных может работать некорректно, так как загружаемые правила предназначены для предыдущей версии программы ""%1"" (%2).
			|Рекомендуется использовать правила из конфигурации или загрузить комплект правил, предназначенный для текущей версии программы (%3).'");
			ВидОшибки = "УстаревшиеПравила";
			
		Иначе
			
			ТекстОшибки = НСтр("ru = 'Синхронизация данных может работать некорректно, так как загружаемые правила предназначены для более новой версии программы ""%1"" (%2).
			|Рекомендуется обновить версию программы или использовать комплект правил, предназначенный для текущей версии программы (%3).'");
			ВидОшибки = "УстаревшаяВерсияКонфигурации";
			
		КонецЕсли;
		
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстОшибки,
			Метаданные.Синоним, ВерсияВПравилах, ВерсияКонфигурации);
		
		ОписаниеОшибки = Новый Структура;
		ОписаниеОшибки.Вставить("ТекстОшибки", ТекстОшибки);
		ОписаниеОшибки.Вставить("ВидОшибки",   ВидОшибки);
		ОписаниеОшибки.Вставить("Картинка",    БиблиотекаКартинок.Предупреждение32);
		
		Возврат Ложь;
		
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

#КонецОбласти
	
#Область СлужебныеПроцедурыИФункции

// Загружает поставляемые правила для плана обмена.
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена, для которого загружаются правила.
//  ИмяФайлаПравил - Строка - полное имя файла правил обмена (*.zip).
//
Процедура ЗагрузитьПоставляемыеПравила(ИмяПланаОбмена, ИмяФайлаПравил) Экспорт
	
	Файл = Новый Файл(ИмяФайлаПравил);
	ИмяФайла = Файл.Имя;
	
	// Распаковываем архив
	ИмяВременногоКаталога = ПолучитьИмяВременногоФайла("");
	Если ОбменДаннымиСервер.РаспаковатьZipФайл(ИмяФайлаПравил, ИмяВременногоКаталога) Тогда
		
		СписокРаспакованныхФайлов = НайтиФайлы(ИмяВременногоКаталога, ПолучитьМаскуВсеФайлы(), Истина);
		
		// В архиве не было ни одного файла - отказываемся от загрузки.
		Если СписокРаспакованныхФайлов.Количество() = 0 Тогда
			ВызватьИсключение НСтр("ru = 'При распаковке архива не найден файл с правилами.'");
		КонецЕсли;
		
		// В архиве количество файлов не соответствует ожидаемому - отказываемся от загрузки.
		Если СписокРаспакованныхФайлов.Количество() <> 3 Тогда
			ВызватьИсключение НСтр("ru = 'Неверный формат комплекта правил. Ожидаемое количество файлов в архиве - три. Ожидаются файлы:
			|ExchangeRules.xml - правила конвертации для текущей программы;
			|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента;
			|RegistrationRules.xml - правила регистрации для текущей программы.'");
		КонецЕсли;
		
		// Закладываем полученный файл правил обратно в двоичные данные.
		Для Каждого ПолученныйФайл Из СписокРаспакованныхФайлов Цикл
			
			Если ПолученныйФайл.Имя = "ExchangeRules.xml" Тогда
				ДвоичныеДанные = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
			ИначеЕсли ПолученныйФайл.Имя ="CorrespondentExchangeRules.xml" Тогда
				ДвоичныеДанныеКорреспондента = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
			ИначеЕсли ПолученныйФайл.Имя ="RegistrationRules.xml" Тогда
				ДвоичныеДанныеРегистрации = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
			Иначе
				ВызватьИсключение НСтр("ru = 'Имена файлов в архиве не соответствуют ожидаемым. Ожидаются файлы:
				|ExchangeRules.xml - правила конвертации для текущей программы;
				|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента;
				|RegistrationRules.xml - правила регистрации для текущей программы.'");
			КонецЕсли;
			
		КонецЦикла;
		
	Иначе
		// Если не удалось распаковать файл - отказываемся от загрузки.
		ВызватьИсключение НСтр("ru = 'Не удалось распаковать архив с правилами.'");
	КонецЕсли;
	
	// Удаляем временный архив и временный каталог с ним.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоКаталога);
	
	ИнформацияОПравилахКонвертации = "[ИнформацияОПравилахИсточника]
		|
		|[ИнформацияОПравилахКорреспондента]";
		
	// Получаем имя временного файла конвертации в локальной ФС на сервере.
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
	
	// Получаем файл правил для зачитки.
	ДвоичныеДанные.Записать(ИмяВременногоФайла);
	
	// Зачитываем правила конвертации.
	КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Выгрузка", ИмяПланаОбмена);
	
	ОбменДаннымиСервер.УстановитьНастройкиОтладкиВыгрузкиДляПравилОбмена(КонвертацияОбъектовИнформационныхБаз, ИмяПланаОбмена, Ложь);
	
	ПравилаЗачитанные = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайла);
	
	ИнформацияОПравилахИсточника = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Ложь);
	
	// Получаем имя временного файла конвертации корреспондента в локальной ФС на сервере.
	ИмяВременногоФайлаКорреспондента = ПолучитьИмяВременногоФайла("xml");
	// Получаем файл правил для зачитки.
	ДвоичныеДанныеКорреспондента.Записать(ИмяВременногоФайлаКорреспондента);
	
	// Зачитываем правила конвертации.
	КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Загрузка", ИмяПланаОбмена);
	
	// методы обработки
	ПравилаЗачитанныеКорреспондента = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайлаКорреспондента);
	
	ИнформацияОПравилахКорреспондента = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Истина);
	
	ИнформацияОПравилахКонвертации = СтрЗаменить(ИнформацияОПравилахКонвертации, "[ИнформацияОПравилахИсточника]", ИнформацияОПравилахИсточника);
	ИнформацияОПравилахКонвертации = СтрЗаменить(ИнформацияОПравилахКонвертации, "[ИнформацияОПравилахКорреспондента]", ИнформацияОПравилахКорреспондента);
	
	// Удаляем временные файлы правил.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайла);
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайлаКорреспондента);
	
	// Сделаем запись правил конвертации.
	ЗаписьПравилКонвертации = СоздатьМенеджерЗаписи();
	ЗаписьПравилКонвертации.ИмяПланаОбмена = ИмяПланаОбмена;
	ЗаписьПравилКонвертации.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов;
	ЗаписьПравилКонвертации.ИмяМакетаПравил = "ПравилаОбмена";
	ЗаписьПравилКонвертации.ИмяМакетаПравилКорреспондента = "ПравилаОбменаКорреспондента";
	ЗаписьПравилКонвертации.ИмяПланаОбменаИзПравил = ИмяПланаОбмена;
	ЗаписьПравилКонвертации.ИмяФайлаПравил = ИмяФайла;
	ЗаписьПравилКонвертации.ИнформацияОПравилах = ИнформацияОПравилахКонвертации;
	ЗаписьПравилКонвертации.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.Файл;
	ЗаписьПравилКонвертации.ПравилаXML = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
	ЗаписьПравилКонвертации.ПравилаXMLКорреспондента = Новый ХранилищеЗначения(ДвоичныеДанныеКорреспондента, Новый СжатиеДанных());
	ЗаписьПравилКонвертации.ПравилаЗачитанные = Новый ХранилищеЗначения(ПравилаЗачитанные);
	ЗаписьПравилКонвертации.ПравилаЗачитанныеКорреспондента = Новый ХранилищеЗначения(ПравилаЗачитанныеКорреспондента);
	ЗаписьПравилКонвертации.РежимОтладки = Ложь;
	ЗаписьПравилКонвертации.ПравилаЗагружены = Истина;
	ЗаписьПравилКонвертации.Записать();
	
	ЗагрузитьПравилаРегистрацииОбъектов(ДвоичныеДанныеРегистрации, ИмяФайла, ИмяПланаОбмена);
		
КонецПроцедуры

// Загружает поставляемые правила регистрации объектов для плана обмена.
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена, для которого загружаются правила.
//  ИмяФайлаПравил - Строка - полное имя файла правил регистрации объектов (*.xml).
//
Процедура ЗагрузитьПоставляемыеПравилаРегистрацииОбъектов(ИмяПланаОбмена, ИмяФайлаПравил) Экспорт
	
	Файл = Новый Файл(ИмяФайлаПравил);
	ИмяФайла = Файл.Имя;
	
	ДвоичныеДанныеРегистрации = Новый ДвоичныеДанные(ИмяФайлаПравил);
	
	ЗагрузитьПравилаРегистрацииОбъектов(ДвоичныеДанныеРегистрации, ИмяФайла, ИмяПланаОбмена);
	
КонецПроцедуры

Процедура ЗагрузитьПравилаРегистрацииОбъектов(ДвоичныеДанные, ИмяФайла, ИмяПланаОбмена)
	
	// Получаем имя временного файла регистрации в локальной ФС на сервере.
	ИмяВременногоФайлаРегистрации = ПолучитьИмяВременногоФайла("xml");
	// Получаем файл правил для зачитки.
	ДвоичныеДанные.Записать(ИмяВременногоФайлаРегистрации);
	
	// Зачитываем правила регистрации.
	ЗагрузкаПравилРегистрации = Обработки.ЗагрузкаПравилРегистрацииОбъектов.Создать();
	
	// свойства обработки
	ЗагрузкаПравилРегистрации.ИмяПланаОбменаДляЗагрузки = ИмяПланаОбмена;
	
	// методы обработки
	ЗагрузкаПравилРегистрации.ЗагрузитьПравила(ИмяВременногоФайлаРегистрации);
	ПравилаРегистрацииЗачитанные   = ЗагрузкаПравилРегистрации.ПравилаРегистрацииОбъектов;
	ИнформацияОПравилахРегистрации = ЗагрузкаПравилРегистрации.ИнформацияОПравилах();
	
	Если ЗагрузкаПравилРегистрации.ФлагОшибки Тогда
		ВызватьИсключение НСтр("ru = 'Ошибка при загрузке правил регистрации.'");
	КонецЕсли;
	
	// Удаляем временные файлы правил.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайлаРегистрации);
	
	// Сделаем запись правил регистрации.
	ЗаписьПравилРегистрации = СоздатьМенеджерЗаписи();
	ЗаписьПравилРегистрации.ИмяПланаОбмена = ИмяПланаОбмена;
	ЗаписьПравилРегистрации.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов;
	ЗаписьПравилРегистрации.ИмяМакетаПравил = "ПравилаРегистрации";
	ЗаписьПравилРегистрации.ИмяПланаОбменаИзПравил = ИмяПланаОбмена;
	ЗаписьПравилРегистрации.ИмяФайлаПравил = ИмяФайла;
	ЗаписьПравилРегистрации.ИнформацияОПравилах = ИнформацияОПравилахРегистрации;
	ЗаписьПравилРегистрации.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.Файл;
	ЗаписьПравилРегистрации.ПравилаXML = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
	ЗаписьПравилРегистрации.ПравилаЗачитанные = Новый ХранилищеЗначения(ПравилаРегистрацииЗачитанные);
	ЗаписьПравилРегистрации.ПравилаЗагружены = Истина;
	ЗаписьПравилРегистрации.Записать();
	
КонецПроцедуры

// Удаляет поставляемые правила для плана обмена (очищает данные в регистре).
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена, для которого удаляются правила.
//
Процедура УдалитьПоставляемыеПравила(ИмяПланаОбмена) Экспорт
	
	Для Каждого ВидПравил Из Перечисления.ВидыПравилДляОбменаДанными Цикл
		УдалитьПравила(ИмяПланаОбмена, ВидПравил);
	КонецЦикла;
	
КонецПроцедуры

// Удаляет поставляемые правила регистрации объектов для плана обмена (очищает данные в регистре).
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена, для которого удаляются правила.
//
Процедура УдалитьПоставляемыеПравилаРегистрацииОбъектов(ИмяПланаОбмена) Экспорт
	
	УдалитьПравила(ИмяПланаОбмена, Перечисления.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов);
	
КонецПроцедуры

Процедура УдалитьПравила(ИмяПланаОбмена, ВидПравил)
	
	МенеджерЗаписи = СоздатьМенеджерЗаписи();
	МенеджерЗаписи.ВидПравил = ВидПравил;
	МенеджерЗаписи.ИмяПланаОбмена = ИмяПланаОбмена;
	МенеджерЗаписи.Прочитать();
	МенеджерЗаписи.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.МакетКонфигурации;
	ЕстьОшибки = Ложь;
	ЗагрузитьПравила(ЕстьОшибки, МенеджерЗаписи);
	Если ЕстьОшибки Тогда
		ВызватьИсключение НСтр("ru = 'Ошибка при загрузке правил из конфигурации.'");
	Иначе
		МенеджерЗаписи.Записать();
	КонецЕсли;
	
КонецПроцедуры

// Определяет, используются ли типовых правила конвертации для плана обмена.
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена, для которого загружаются правила.
//
// Возвращаемое значение:
//   Булево - если Истина, то используются; Ложь - нет.
//
Функция ИспользуютсяТиповыеПравила(ИмяПланаОбмена) Экспорт
	ТекстЗапроса = "
	|ВЫБРАТЬ
	|	ПравилаДляОбменаДанными.ПравилаXML КАК ПравилаXML
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	  ПравилаДляОбменаДанными.ИмяПланаОбмена = &ИмяПланаОбмена
	|	И ПравилаДляОбменаДанными.ВидПравил      = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов)
	|	И ПравилаДляОбменаДанными.ПравилаЗагружены
	|";
	
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("ИмяПланаОбмена", ИмяПланаОбмена);
	
	Результат = Запрос.Выполнить();
	
	Если Результат.Пустой() Тогда
		Возврат Ложь;
	КонецЕсли;
	Выборка = Результат.Выбрать();
	Выборка.Следующий();
	
	ДвоичныеДанныеПравил = Выборка.ПравилаXML.Получить(); // ДвоичныеДанные
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
	ДвоичныеДанныеПравил.Записать(ИмяВременногоФайла);
	
	ПравилаОбмена = Новый ЧтениеXML();
	ПравилаОбмена.ОткрытьФайл(ИмяВременногоФайла);
	ПравилаТиповые = Ложь;
	Пока ПравилаОбмена.Прочитать() Цикл
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		Если ИмяУзла = "ВерсияФормата" Тогда
			Пока ПравилаОбмена.ПрочитатьАтрибут() Цикл
				Если ПравилаОбмена.ЛокальноеИмя = "Типовые" Тогда
					ПравилаТиповые = Истина;
					Прервать;
				КонецЕсли;
			КонецЦикла;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	ПравилаОбмена.Закрыть();
	УдалитьФайлы(ИмяВременногоФайла);
	
	Возврат ПравилаТиповые;
КонецФункции

// Параметры:
//   РежимОбмена - Строка
//   ИмяПланаОбмена - Строка
//
// Возвращаемое значение:
//   ОбработкаОбъект.КонвертацияОбъектовИнформационныхБаз
//
Функция НоваяОбработкаКонвертацияОбъектовИнформационныхБаз(РежимОбмена, ИмяПланаОбмена)
	
	КонвертацияОбъектовИнформационныхБаз = Обработки.КонвертацияОбъектовИнформационныхБаз.Создать();
	
	КонвертацияОбъектовИнформационныхБаз.РежимОбмена = РежимОбмена;
	КонвертацияОбъектовИнформационныхБаз.ИмяПланаОбменаВРО = ИмяПланаОбмена;
	
	КонвертацияОбъектовИнформационныхБаз.УстановитьКлючСообщенияЖурналаРегистрации(
		ОбменДаннымиСервер.СобытиеЖурналаРегистрацииЗагрузкаПравилДляОбменаДанными());
		
	Возврат КонвертацияОбъектовИнформационныхБаз;
	
КонецФункции

// Загружает правила в регистр.
//
// Параметры:
//  Отказ - Булево - отказ от записи в регистр.
//  Запись - РегистрСведенийЗапись.ПравилаДляОбменаДанными - запись регистра, в которую будут помещены данные.
//  АдресВременногоХранилища - Строка - адрес временного хранилища, из которого будут загружены XML-правила.
//  ИмяФайлаПравил - Строка - имя файла из которого были загружены файлы(оно также фиксируется в регистре).
//  ДвоичныеДанные - ДвоичныеДанные - данные, в которые сохраняется XML-файл (в том числе и распакованный из ZIP-архива).
//  ЭтоАрхив - Булево - признак того, что правила загружаются из ZIP-архива, а не из XML-файла.
//
Процедура ЗагрузитьПравила(Отказ, Запись, АдресВременногоХранилища = "", ИмяФайлаПравил = "", ЭтоАрхив = Ложь) Экспорт
	
	// Проверка существования плана обмена.
	СписокПлановОбмена = ОбменДаннымиПовтИсп.ПланыОбменаБСП();
	Если СписокПлановОбмена.Найти(Запись.ИмяПланаОбмена) = Неопределено Тогда
		НСтрока = НСтр("ru = 'План обмена %1 не используется для синхронизации данных, правила не обновлены.'");
		НСтрока = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтрока, Запись.ИмяПланаОбмена);
		ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
	Иначе
		// Проверка заполнения обязательных полей записи.
		ВыполнитьПроверкуЗаполненияПолей(Отказ, Запись);
	КонецЕсли;
	
	Если Отказ Тогда
		Возврат;
	КонецЕсли;
	
	ЭтоПравилаКонвертации = (Запись.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов);
	
	// Получаем двоичные данные правил из файла или макета конфигурации.
	Если Запись.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.МакетКонфигурации Тогда
		
		ДвоичныеДанные = ДвоичныеДанныеИзМакетаКонфигурации(Отказ, Запись.ИмяПланаОбмена, Запись.ИмяМакетаПравил);
		
		Если ЭтоПравилаКонвертации Тогда
			
			Если ПустаяСтрока(Запись.ИмяМакетаПравилКорреспондента) Тогда
				Запись.ИмяМакетаПравилКорреспондента = Запись.ИмяМакетаПравил + "Корреспондента";
			КонецЕсли;
			ДвоичныеДанныеКорреспондента = ДвоичныеДанныеИзМакетаКонфигурации(Отказ, Запись.ИмяПланаОбмена, Запись.ИмяМакетаПравилКорреспондента);
			
		КонецЕсли;
		
	Иначе
		
		ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
		
	КонецЕсли;
	
	// Если это архив, тогда разархивируем его и заново заложим в двоичные данные для дальнейшей работы.
	Если ЭтоАрхив Тогда
		
		// Получаем файл архива из двоичных данных.
		ИмяВременногоАрхива = ПолучитьИмяВременногоФайла("zip");
		ДвоичныеДанные.Записать(ИмяВременногоАрхива);
		
		// Распаковываем архив
		ИмяВременногоКаталога = ПолучитьИмяВременногоФайла("");
		Если ОбменДаннымиСервер.РаспаковатьZipФайл(ИмяВременногоАрхива, ИмяВременногоКаталога) Тогда
			
			СписокРаспакованныхФайлов = НайтиФайлы(ИмяВременногоКаталога, ПолучитьМаскуВсеФайлы(), Истина);
			
			// В архиве не было ни одного файла - отказываемся от загрузки.
			Если СписокРаспакованныхФайлов.Количество() = 0 Тогда
				НСтрока = НСтр("ru = 'При распаковке архива не найден файл с правилами.'");
				ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
			КонецЕсли;
			
			Если ЭтоПравилаКонвертации Тогда
				
				// Закладываем полученный файл правил обратно в двоичные данные.
				Если СписокРаспакованныхФайлов.Количество() = 2 Тогда
					
					Если СписокРаспакованныхФайлов[0].Имя = "ExchangeRules.xml" 
						И СписокРаспакованныхФайлов[1].Имя ="CorrespondentExchangeRules.xml" Тогда
						
						ДвоичныеДанные = Новый ДвоичныеДанные(СписокРаспакованныхФайлов[0].ПолноеИмя);
						ДвоичныеДанныеКорреспондента = Новый ДвоичныеДанные(СписокРаспакованныхФайлов[1].ПолноеИмя);
						
					ИначеЕсли СписокРаспакованныхФайлов[1].Имя = "ExchangeRules.xml" 
						И СписокРаспакованныхФайлов[0].Имя ="CorrespondentExchangeRules.xml" Тогда
						
						ДвоичныеДанные = Новый ДвоичныеДанные(СписокРаспакованныхФайлов[1].ПолноеИмя);
						ДвоичныеДанныеКорреспондента = Новый ДвоичныеДанные(СписокРаспакованныхФайлов[0].ПолноеИмя);
						
					Иначе
						
						НСтрока = НСтр("ru = 'Имена файлов в архиве не соответствуют ожидаемым. Ожидаются файлы:
							|ExchangeRules.xml - правила конвертации для текущей программы;
							|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента.'");
						ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
						
					КонецЕсли;
					
				// Старый формат
				ИначеЕсли СписокРаспакованныхФайлов.Количество() = 1 Тогда
					НСтрока = НСтр("ru = 'В архиве найден один файл правил конвертации. Ожидаемое количество файлов в архиве - два. Ожидаются файлы:
						|ExchangeRules.xml - правила конвертации для текущей программы;
						|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента.'");
					ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
				// В архиве оказалось несколько файлов, хотя должен быть один - отказываемся от загрузки.
				ИначеЕсли СписокРаспакованныхФайлов.Количество() > 1 Тогда
					НСтрока = НСтр("ru = 'При распаковке архива найдено несколько файлов. Должен быть только один файл с правилами.'");
					ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
				КонецЕсли;
				
			Иначе
				
				// Закладываем полученный файл правил обратно в двоичные данные.
				Если СписокРаспакованныхФайлов.Количество() = 1 Тогда
					ДвоичныеДанные = Новый ДвоичныеДанные(СписокРаспакованныхФайлов[0].ПолноеИмя);
					
				// В архиве оказалось несколько файлов, хотя должен быть один - отказываемся от загрузки.
				ИначеЕсли СписокРаспакованныхФайлов.Количество() > 1 Тогда
					НСтрока = НСтр("ru = 'При распаковке архива найдено несколько файлов. Должен быть только один файл с правилами.'");
					ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
				КонецЕсли;
				
			КонецЕсли;
			
		Иначе // Если не удалось распаковать файл - отказываемся от загрузки.
			НСтрока = НСтр("ru = 'Не удалось распаковать архив с правилами.'");
			ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
		КонецЕсли;
		
		// Удаляем временный архив и временный каталог с ним.
		ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоКаталога);
		ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоАрхива);
		
	КонецЕсли;
	
	Если Отказ Тогда
		Возврат;
	КонецЕсли;
	
	// Получаем имя временного файла в локальной ФС на сервере.
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
	
	// Получаем файл правил для зачитки.
	ДвоичныеДанные.Записать(ИмяВременногоФайла);
	
	Если ЭтоПравилаКонвертации Тогда
		
		// Зачитываем правила конвертации.
		КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Выгрузка", Запись.ИмяПланаОбмена);
		
		ОбменДаннымиСервер.УстановитьНастройкиОтладкиВыгрузкиДляПравилОбмена(КонвертацияОбъектовИнформационныхБаз, Запись.ИмяПланаОбмена, Запись.РежимОтладки);
		
		// методы обработки
		ПравилаЗачитанные = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайла);
		
		ИнформацияОПравилах = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Ложь);
		
		Если КонвертацияОбъектовИнформационныхБаз.ФлагОшибки() Тогда
			Отказ = Истина;
		КонецЕсли;
		
		// Получаем имя временного файла в локальной ФС на сервере.
		ИмяВременногоФайлаКорреспондента = ПолучитьИмяВременногоФайла("xml");
		// Получаем файл правил для зачитки.
		ДвоичныеДанныеКорреспондента.Записать(ИмяВременногоФайлаКорреспондента);
		
		// Зачитываем правила конвертации.
		КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Загрузка", Запись.ИмяПланаОбмена);
		
		// методы обработки
		ПравилаЗачитанныеКорреспондента = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайлаКорреспондента);
		
		УдалитьФайлы(ИмяВременногоФайлаКорреспондента);
		
		ИнформацияОПравилахКорреспондента = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Истина);
		
		Если КонвертацияОбъектовИнформационныхБаз.ФлагОшибки() Тогда
			Отказ = Истина;
		КонецЕсли;
		
 		ИнформацияОПравилах = ИнформацияОПравилах + Символы.ПС + Символы.ПС + ИнформацияОПравилахКорреспондента;
		
	Иначе // ПравилаРегистрацииОбъектов
		
		// Зачитываем правила регистрации.
		ЗагрузкаПравилРегистрации = Обработки.ЗагрузкаПравилРегистрацииОбъектов.Создать();
		
		// свойства обработки
		ЗагрузкаПравилРегистрации.ИмяПланаОбменаДляЗагрузки = Запись.ИмяПланаОбмена;
		
		// методы обработки
		ЗагрузкаПравилРегистрации.ЗагрузитьПравила(ИмяВременногоФайла);
		
		ПравилаЗачитанные = ЗагрузкаПравилРегистрации.ПравилаРегистрацииОбъектов;
		
		ИнформацияОПравилах = ЗагрузкаПравилРегистрации.ИнформацияОПравилах();
		
		Если ЗагрузкаПравилРегистрации.ФлагОшибки Тогда
			Отказ = Истина;
		КонецЕсли;
		
	КонецЕсли;
	
	// Удаляем временный файл правил.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайла);
	
	Если Не Отказ Тогда
		
		Запись.ПравилаXML          = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
		Запись.ПравилаЗачитанные   = Новый ХранилищеЗначения(ПравилаЗачитанные);
		
		Если ЭтоПравилаКонвертации Тогда
			
			Запись.ПравилаXMLКорреспондента = Новый ХранилищеЗначения(ДвоичныеДанныеКорреспондента, Новый СжатиеДанных());
			Запись.ПравилаЗачитанныеКорреспондента = Новый ХранилищеЗначения(ПравилаЗачитанныеКорреспондента);
			
		КонецЕсли;
		
		Запись.ИнформацияОПравилах = ИнформацияОПравилах;
		Запись.ИмяФайлаПравил = ИмяФайлаПравил;
		Запись.ПравилаЗагружены = Истина;
		Запись.ИмяПланаОбменаИзПравил = Запись.ИмяПланаОбмена;
		
	КонецЕсли;
	
КонецПроцедуры

Процедура ЗагрузитьКомплектПравил(Отказ, ДанныеДляЗаписи, ОписаниеОшибки, АдресВременногоХранилища = "", ИмяФайлаПравил = "") Экспорт
	
	ЗаписьПравилКонвертации = ДанныеДляЗаписи.ЗаписьПравилКонвертации;
	ЗаписьПравилРегистрации = ДанныеДляЗаписи.ЗаписьПравилРегистрации;
	
	// Получаем двоичные данные правил из файла или макета конфигурации.
	Если ЗаписьПравилКонвертации.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.МакетКонфигурации Тогда
		
		ДвоичныеДанные               = ДвоичныеДанныеИзМакетаКонфигурации(Отказ, ЗаписьПравилКонвертации.ИмяПланаОбмена, ЗаписьПравилКонвертации.ИмяМакетаПравил);
		ДвоичныеДанныеКорреспондента = ДвоичныеДанныеИзМакетаКонфигурации(Отказ, ЗаписьПравилКонвертации.ИмяПланаОбмена, ЗаписьПравилКонвертации.ИмяМакетаПравилКорреспондента);
		ДвоичныеДанныеРегистрации    = ДвоичныеДанныеИзМакетаКонфигурации(Отказ, ЗаписьПравилРегистрации.ИмяПланаОбмена, ЗаписьПравилРегистрации.ИмяМакетаПравил);
		
	Иначе
		
		ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
		
	КонецЕсли;
	
	Если ЗаписьПравилКонвертации.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.Файл Тогда
		
		// Получаем файл архива из двоичных данных.
		ИмяВременногоАрхива = ПолучитьИмяВременногоФайла("zip");
		ДвоичныеДанные.Записать(ИмяВременногоАрхива);
		
		// Распаковываем архив
		ИмяВременногоКаталога = ПолучитьИмяВременногоФайла("");
		Если ОбменДаннымиСервер.РаспаковатьZipФайл(ИмяВременногоАрхива, ИмяВременногоКаталога) Тогда
			
			СписокРаспакованныхФайлов = НайтиФайлы(ИмяВременногоКаталога, ПолучитьМаскуВсеФайлы(), Истина);
			
			// В архиве не было ни одного файла - отказываемся от загрузки.
			Если СписокРаспакованныхФайлов.Количество() = 0 Тогда
				НСтрока = НСтр("ru = 'При распаковке архива не найден файл с правилами.'");
				ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
			КонецЕсли;
			
			// В архиве количество файлов не соответствует ожидаемому - отказываемся от загрузки.
			Если СписокРаспакованныхФайлов.Количество() <> 3 Тогда
				НСтрока = НСтр("ru = 'Неверный формат комплекта правил. Ожидаемое количество файлов в архиве - три. Ожидаются файлы:
					|ExchangeRules.xml - правила конвертации для текущей программы;
					|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента;
					|RegistrationRules.xml - правила регистрации для текущей программы.'");
				ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
			КонецЕсли;
				
			// Закладываем полученный файл правил обратно в двоичные данные.
			Для Каждого ПолученныйФайл Из СписокРаспакованныхФайлов Цикл
				
				Если ПолученныйФайл.Имя = "ExchangeRules.xml" Тогда
					ДвоичныеДанные = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
				ИначеЕсли ПолученныйФайл.Имя ="CorrespondentExchangeRules.xml" Тогда
					ДвоичныеДанныеКорреспондента = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
				ИначеЕсли ПолученныйФайл.Имя ="RegistrationRules.xml" Тогда
					ДвоичныеДанныеРегистрации = Новый ДвоичныеДанные(ПолученныйФайл.ПолноеИмя);
				Иначе
					НСтрока = НСтр("ru = 'Имена файлов в архиве не соответствуют ожидаемым. Ожидаются файлы:
						|ExchangeRules.xml - правила конвертации для текущей программы;
					|CorrespondentExchangeRules.xml - правила конвертации для программы-корреспондента;
					|RegistrationRules.xml - правила регистрации для текущей программы.'");
					ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
					Прервать;
				КонецЕсли;
				
			КонецЦикла;
			
		Иначе 
			// Если не удалось распаковать файл - отказываемся от загрузки.
			НСтрока = НСтр("ru = 'Не удалось распаковать архив с правилами.'");
			ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
		КонецЕсли;
		
		// Удаляем временный архив и временный каталог с ним.
		ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоКаталога);
		ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоАрхива);
		
	КонецЕсли;
	
	Если Отказ Тогда
		Возврат;
	КонецЕсли;
	
	ИнформацияОПравилахКонвертации = "[ИнформацияОПравилахИсточника]
		|
		|[ИнформацияОПравилахКорреспондента]";
		
	// Получаем имя временного файла конвертации в локальной ФС на сервере.
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
	
	// Получаем файл правил для зачитки.
	ДвоичныеДанные.Записать(ИмяВременногоФайла);
	
	// Зачитываем правила конвертации.
	КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Выгрузка", ЗаписьПравилКонвертации.ИмяПланаОбмена);
	
	ОбменДаннымиСервер.УстановитьНастройкиОтладкиВыгрузкиДляПравилОбмена(КонвертацияОбъектовИнформационныхБаз, ЗаписьПравилКонвертации.ИмяПланаОбмена, ЗаписьПравилКонвертации.РежимОтладки);
	
	// методы обработки
	Если ЗаписьПравилКонвертации.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.Файл И ОписаниеОшибки = Неопределено
		И Не ПравилаКонвертацииСовместимыСТекущейВерсией(ЗаписьПравилКонвертации.ИмяПланаОбмена, ОписаниеОшибки, ИнформацияОПравилахИзФайла(ИмяВременногоФайла)) Тогда
		
		Отказ = Истина;
		Возврат;
		
	КонецЕсли;
	
	ПравилаЗачитанные = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайла);
	
	ИнформацияОПравилахИсточника = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Ложь);
	
	Если КонвертацияОбъектовИнформационныхБаз.ФлагОшибки() Тогда
		Отказ = Истина;
	КонецЕсли;
	
	// Получаем имя временного файла конвертации корреспондента в локальной ФС на сервере.
	ИмяВременногоФайлаКорреспондента = ПолучитьИмяВременногоФайла("xml");
	// Получаем файл правил для зачитки.
	ДвоичныеДанныеКорреспондента.Записать(ИмяВременногоФайлаКорреспондента);
	
	// Зачитываем правила конвертации.
	КонвертацияОбъектовИнформационныхБаз = НоваяОбработкаКонвертацияОбъектовИнформационныхБаз("Загрузка", ЗаписьПравилКонвертации.ИмяПланаОбмена);
	
	// методы обработки
	ПравилаЗачитанныеКорреспондента = КонвертацияОбъектовИнформационныхБаз.ПравилаОбмена(ИмяВременногоФайлаКорреспондента);
	
	ИнформацияОПравилахКорреспондента = КонвертацияОбъектовИнформационныхБаз.ИнформацияОПравилах(Истина);
	
	Если КонвертацияОбъектовИнформационныхБаз.ФлагОшибки() Тогда
		Отказ = Истина;
	КонецЕсли;
	
	ИнформацияОПравилахКонвертации = СтрЗаменить(ИнформацияОПравилахКонвертации, "[ИнформацияОПравилахИсточника]", ИнформацияОПравилахИсточника);
	ИнформацияОПравилахКонвертации = СтрЗаменить(ИнформацияОПравилахКонвертации, "[ИнформацияОПравилахКорреспондента]", ИнформацияОПравилахКорреспондента);
	
	// Получаем имя временного файла регистрации в локальной ФС на сервере.
	ИмяВременногоФайлаРегистрации = ПолучитьИмяВременногоФайла("xml");
	// Получаем файл правил для зачитки.
	ДвоичныеДанныеРегистрации.Записать(ИмяВременногоФайлаРегистрации);

	
	// Зачитываем правила регистрации.
	ЗагрузкаПравилРегистрации = Обработки.ЗагрузкаПравилРегистрацииОбъектов.Создать();
	
	// свойства обработки
	ЗагрузкаПравилРегистрации.ИмяПланаОбменаДляЗагрузки = ЗаписьПравилРегистрации.ИмяПланаОбмена;
	
	// методы обработки
	ЗагрузкаПравилРегистрации.ЗагрузитьПравила(ИмяВременногоФайлаРегистрации);
	ПравилаРегистрацииЗачитанные   = ЗагрузкаПравилРегистрации.ПравилаРегистрацииОбъектов;
	ИнформацияОПравилахРегистрации = ЗагрузкаПравилРегистрации.ИнформацияОПравилах();
	
	Если ЗагрузкаПравилРегистрации.ФлагОшибки Тогда
		Отказ = Истина;
	КонецЕсли;
	
	// Удаляем временные файлы правил.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайла);
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайлаКорреспондента);
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайлаРегистрации);
	
	Если Не Отказ Тогда
		
		// Сделаем запись правил конвертации.
		ЗаписьПравилКонвертации.ПравилаXML                      = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
		ЗаписьПравилКонвертации.ПравилаЗачитанные               = Новый ХранилищеЗначения(ПравилаЗачитанные);
		ЗаписьПравилКонвертации.ПравилаXMLКорреспондента        = Новый ХранилищеЗначения(ДвоичныеДанныеКорреспондента, Новый СжатиеДанных());
		ЗаписьПравилКонвертации.ПравилаЗачитанныеКорреспондента = Новый ХранилищеЗначения(ПравилаЗачитанныеКорреспондента);
		ЗаписьПравилКонвертации.ИнформацияОПравилах             = ИнформацияОПравилахКонвертации;
		ЗаписьПравилКонвертации.ИмяФайлаПравил                  = ИмяФайлаПравил;
		ЗаписьПравилКонвертации.ПравилаЗагружены                = Истина;
		ЗаписьПравилКонвертации.ИмяПланаОбменаИзПравил          = ЗаписьПравилКонвертации.ИмяПланаОбмена;
		
		// Сделаем запись правил регистрации.
		ЗаписьПравилРегистрации.ПравилаXML             = Новый ХранилищеЗначения(ДвоичныеДанныеРегистрации, Новый СжатиеДанных());
		ЗаписьПравилРегистрации.ПравилаЗачитанные      = Новый ХранилищеЗначения(ПравилаРегистрацииЗачитанные);
		ЗаписьПравилРегистрации.ИнформацияОПравилах    = ИнформацияОПравилахРегистрации;
		ЗаписьПравилРегистрации.ИмяФайлаПравил         = ИмяФайлаПравил;
		ЗаписьПравилРегистрации.ПравилаЗагружены       = Истина;
		ЗаписьПравилРегистрации.ИмяПланаОбменаИзПравил = ЗаписьПравилРегистрации.ИмяПланаОбмена;
		
	КонецЕсли;
	
КонецПроцедуры

// Получает зачитанные правила конвертации объектов из ИБ для плана обмена.
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена как объекта метаданных.
// 
// Возвращаемое значение:
//  ПравилаЗачитанные - ХранилищеЗначения - зачитанные правила конвертации объектов.
//  Неопределено - если правила конвертации не были загружены в базу для плана обмена.
//
Функция ЗачитанныеПравилаКонвертацииОбъектов(Знач ИмяПланаОбмена, ПолучатьПравилаКорреспондента = Ложь) Экспорт
	
	// Возвращаемое значение функции.
	ПравилаЗачитанные = Неопределено;
	
	ШаблонТекстаЗапроса = 
	"ВЫБРАТЬ
	|	&ИмяРеквизита КАК ПравилаЗачитанные
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ИмяПланаОбмена = &ИмяПланаОбмена
	|	И ПравилаДляОбменаДанными.ВидПравил = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов)
	|	И ПравилаДляОбменаДанными.ПравилаЗагружены";
	
	ИмяРеквизита = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("ПравилаДляОбменаДанными.%1",
		?(ПолучатьПравилаКорреспондента, "ПравилаЗачитанныеКорреспондента", "ПравилаЗачитанные"));
	
	ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ИмяРеквизита", ИмяРеквизита);
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ИмяПланаОбмена", ИмяПланаОбмена);
	
	Результат = Запрос.Выполнить();
	
	Если Не Результат.Пустой() Тогда
		
		Выборка = Результат.Выбрать();
		Выборка.Следующий();
		
		ПравилаЗачитанные = Выборка.ПравилаЗачитанные;
		
	КонецЕсли;
	
	Возврат ПравилаЗачитанные;
	
КонецФункции

Функция ИспользуютсяПравилаИзФайла(ИмяПланаОбмена, ПодробныйРезультат = Ложь) Экспорт
	
	Запрос = Новый Запрос(
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ПравилаДляОбменаДанными.ИмяПланаОбмена КАК ИмяПланаОбмена,
	|	ПравилаДляОбменаДанными.ВидПравил КАК ВидПравил
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ИсточникПравил = ЗНАЧЕНИЕ(Перечисление.ИсточникиПравилДляОбменаДанными.Файл)
	|	И ПравилаДляОбменаДанными.ПравилаЗагружены
	|	И ПравилаДляОбменаДанными.ИмяПланаОбмена = &ИмяПланаОбмена");
	Запрос.УстановитьПараметр("ИмяПланаОбмена", ИмяПланаОбмена);
	
	Результат = Запрос.Выполнить();
	
	Если ПодробныйРезультат Тогда
		
		ПравилаИзФайла = Новый Структура("ПравилаРегистрации, ПравилаКонвертации", Ложь, Ложь);
		
		Выборка = Результат.Выбрать();
		Пока Выборка.Следующий() Цикл
			Если Выборка.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов Тогда
				ПравилаИзФайла.ПравилаКонвертации = Истина;
			ИначеЕсли Выборка.ВидПравил = Перечисления.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов Тогда
				ПравилаИзФайла.ПравилаРегистрации = Истина;
			КонецЕсли;
		КонецЦикла;
		
		Возврат ПравилаИзФайла;
		
	Иначе
		Возврат Не Результат.Пустой();
	КонецЕсли;
	
КонецФункции

Функция ДвоичныеДанныеИзМакетаКонфигурации(Отказ, ИмяПланаОбмена, ИмяМакета)
	
	// Получаем имя временного файла в локальной ФС на сервере.
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
	
	ПланОбменаМенеджер = ОбменДаннымиПовтИсп.ПолучитьМенеджерПланаОбменаПоИмени(ИмяПланаОбмена);
	
	// Получаем макет типовых правил.
	Попытка
		МакетПравил = ПланОбменаМенеджер.ПолучитьМакет(ИмяМакета);
	Исключение
		
		СтрокаСообщения = НСтр("ru = 'Ошибка получения макета конфигурации %1 для плана обмена %2'");
		СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, ИмяМакета, ИмяПланаОбмена);
		ОбменДаннымиСервер.СообщитьОбОшибке(СтрокаСообщения, Отказ);
		Возврат Неопределено;
		
	КонецПопытки;
	
	МакетПравил.Записать(ИмяВременногоФайла);
	
	ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
	
	// Удаляем временный файл правил.
	ФайловаяСистема.УдалитьВременныйФайл(ИмяВременногоФайла);
	
	Возврат ДвоичныеДанные;
КонецФункции

Процедура ВыполнитьПроверкуЗаполненияПолей(Отказ, Запись)
	
	Если ПустаяСтрока(Запись.ИмяПланаОбмена) Тогда
		
		НСтрока = НСтр("ru = 'Укажите план обмена.'");
		
		ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
		
	ИначеЕсли Запись.ИсточникПравил = Перечисления.ИсточникиПравилДляОбменаДанными.МакетКонфигурации
		    И ПустаяСтрока(Запись.ИмяМакетаПравил) Тогда
		
		НСтрока = НСтр("ru = 'Укажите типовые правила.'");
		
		ОбменДаннымиСервер.СообщитьОбОшибке(НСтрока, Отказ);
		
	КонецЕсли;
	
КонецПроцедуры

Функция ИнформацияОПравилахИзФайла(ИмяФайлаПравил)
	
	ПравилаОбмена = Новый ЧтениеXML();
	ПравилаОбмена.ОткрытьФайл(ИмяФайлаПравил);
	ПравилаОбмена.Прочитать();
	
	Если Не ((ПравилаОбмена.ЛокальноеИмя = "ПравилаОбмена") И (ПравилаОбмена.ТипУзла = ТипУзлаXML.НачалоЭлемента)) Тогда
		ВызватьИсключение НСтр("ru = 'Ошибка формата правил обмена'");
	КонецЕсли;
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Источник" И ПравилаОбмена.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			
			ИнформацияОПравилах = Новый Структура;
			ИнформацияОПравилах.Вставить("ВерсияКонфигурации", ПравилаОбмена.ПолучитьАтрибут("ВерсияКонфигурации"));
			ИнформацияОПравилах.Вставить("СинонимКонфигурацииВПравилах", ПравилаОбмена.ПолучитьАтрибут("СинонимКонфигурации"));
			ПравилаОбмена.Прочитать();
			ИнформацияОПравилах.Вставить("ИмяКонфигурации", ПравилаОбмена.Значение);
			
		ИначеЕсли (ИмяУзла = "Источник") И (ПравилаОбмена.ТипУзла = ТипУзлаXML.КонецЭлемента) Тогда
			
			ПравилаОбмена.Закрыть();
			Возврат ИнформацияОПравилах;
			
		КонецЕсли;
		
	КонецЦикла;
	
	ВызватьИсключение НСтр("ru = 'Ошибка формата правил обмена'");
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Профили безопасности

// См. РаботаВБезопасномРежимеПереопределяемый.ПриЗаполненииРазрешенийНаДоступКВнешнимРесурсам.
Процедура ПриЗаполненииРазрешенийНаДоступКВнешнимРесурсам(ЗапросыРазрешений) Экспорт
	
	ЗагруженныеПравила = ЗагруженныеПравила();
	
	Пока ЗагруженныеПравила.Следующий() Цикл
		
		ЗапросНаИспользованиеВнешнихРесурсов(ЗапросыРазрешений, ЗагруженныеПравила);
		
	КонецЦикла;
	
КонецПроцедуры

Функция ПравилаРегистрацииИзФайла(ИмяПланаОбмена) Экспорт
	
	Запрос = Новый Запрос(
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ПравилаЗагружены = ИСТИНА
	|	И ПравилаДляОбменаДанными.ВидПравил = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов)
	|	И ПравилаДляОбменаДанными.ИсточникПравил = ЗНАЧЕНИЕ(Перечисление.ИсточникиПравилДляОбменаДанными.Файл)
	|	И ПравилаДляОбменаДанными.ИмяПланаОбмена = &ИмяПланаОбмена");
	Запрос.УстановитьПараметр("ИмяПланаОбмена", ИмяПланаОбмена);
	
	Возврат Не Запрос.Выполнить().Пустой();
	
КонецФункции

Функция ПравилаКонвертацииИзФайла(ИмяПланаОбмена) Экспорт
	
	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	ПравилаДляОбменаДанными.ИмяПланаОбмена КАК ИмяПланаОбмена,
	|	ПравилаДляОбменаДанными.РежимОтладки КАК РежимОтладки,
	|	ПравилаДляОбменаДанными.РежимОтладкиВыгрузки КАК РежимОтладкиВыгрузки,
	|	ПравилаДляОбменаДанными.РежимОтладкиЗагрузки КАК РежимОтладкиЗагрузки,
	|	ПравилаДляОбменаДанными.РежимПротоколированияОбменаДанными КАК РежимПротоколированияОбменаДанными,
	|	ПравилаДляОбменаДанными.ИмяФайлаОбработкиДляОтладкиВыгрузки КАК ИмяФайлаОбработкиДляОтладкиВыгрузки,
	|	ПравилаДляОбменаДанными.ИмяФайлаОбработкиДляОтладкиЗагрузки КАК ИмяФайлаОбработкиДляОтладкиЗагрузки,
	|	ПравилаДляОбменаДанными.ИмяФайлаПротоколаОбмена КАК ИмяФайлаПротоколаОбмена
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ПравилаЗагружены = ИСТИНА
	|	И ПравилаДляОбменаДанными.ВидПравил = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов)
	|	И ПравилаДляОбменаДанными.ИсточникПравил = ЗНАЧЕНИЕ(Перечисление.ИсточникиПравилДляОбменаДанными.Файл)
	|	И ПравилаДляОбменаДанными.ИмяПланаОбмена = &ИмяПланаОбмена");
	Запрос.УстановитьПараметр("ИмяПланаОбмена", ИмяПланаОбмена);
	
	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка;
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

Функция ЗагруженныеПравила()
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	|	ПравилаДляОбменаДанными.ИмяПланаОбмена,
	|	ПравилаДляОбменаДанными.РежимОтладки,
	|	ПравилаДляОбменаДанными.РежимОтладкиВыгрузки,
	|	ПравилаДляОбменаДанными.РежимОтладкиЗагрузки,
	|	ПравилаДляОбменаДанными.РежимПротоколированияОбменаДанными,
	|	ПравилаДляОбменаДанными.ИмяФайлаОбработкиДляОтладкиВыгрузки,
	|	ПравилаДляОбменаДанными.ИмяФайлаОбработкиДляОтладкиЗагрузки,
	|	ПравилаДляОбменаДанными.ИмяФайлаПротоколаОбмена,
	|	ИСТИНА КАК ЕстьПравилаКонвертации
	|ПОМЕСТИТЬ ПравилаКонвертации
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ВидПравил = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаКонвертацииОбъектов)
	|	И ПравилаДляОбменаДанными.ПравилаЗагружены = ИСТИНА
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ПравилаДляОбменаДанными.ИмяПланаОбмена,
	|	ИСТИНА КАК ПравилаРегистрацииИзФайла
	|ПОМЕСТИТЬ ПравилаРегистрации
	|ИЗ
	|	РегистрСведений.ПравилаДляОбменаДанными КАК ПравилаДляОбменаДанными
	|ГДЕ
	|	ПравилаДляОбменаДанными.ПравилаЗагружены = ИСТИНА
	|	И ПравилаДляОбменаДанными.ВидПравил = ЗНАЧЕНИЕ(Перечисление.ВидыПравилДляОбменаДанными.ПравилаРегистрацииОбъектов)
	|	И ПравилаДляОбменаДанными.ИсточникПравил = ЗНАЧЕНИЕ(Перечисление.ИсточникиПравилДляОбменаДанными.Файл)
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВЫБОР
	|		КОГДА ПравилаРегистрации.ПравилаРегистрацииИзФайла
	|			ТОГДА ПравилаРегистрации.ИмяПланаОбмена
	|		ИНАЧЕ ПравилаКонвертации.ИмяПланаОбмена
	|	КОНЕЦ КАК ИмяПланаОбмена,
	|	ПравилаКонвертации.РежимОтладки,
	|	ПравилаКонвертации.РежимОтладкиВыгрузки,
	|	ПравилаКонвертации.РежимОтладкиЗагрузки,
	|	ПравилаКонвертации.РежимПротоколированияОбменаДанными,
	|	ПравилаКонвертации.ИмяФайлаОбработкиДляОтладкиВыгрузки,
	|	ПравилаКонвертации.ИмяФайлаОбработкиДляОтладкиЗагрузки,
	|	ПравилаКонвертации.ИмяФайлаПротоколаОбмена,
	|	ЕСТЬNULL(ПравилаРегистрации.ПравилаРегистрацииИзФайла, ЛОЖЬ) КАК ПравилаРегистрацииИзФайла,
	|	ЕСТЬNULL(ПравилаКонвертации.ЕстьПравилаКонвертации, ЛОЖЬ) КАК ЕстьПравилаКонвертации
	|ИЗ
	|	ПравилаКонвертации КАК ПравилаКонвертации
	|		ПОЛНОЕ СОЕДИНЕНИЕ ПравилаРегистрации КАК ПравилаРегистрации
	|		ПО ПравилаКонвертации.ИмяПланаОбмена = ПравилаРегистрации.ИмяПланаОбмена";
	
	Возврат Запрос.Выполнить().Выбрать();
	
КонецФункции

Процедура ЗапросНаИспользованиеВнешнихРесурсов(ЗапросыРазрешений, Запись, ЕстьПравилаКонвертации = Неопределено, ПравилаРегистрацииИзФайла = Неопределено) Экспорт
	
	Разрешения = Новый Массив;
	МодульРаботаВБезопасномРежиме = ОбщегоНазначения.ОбщийМодуль("РаботаВБезопасномРежиме");
	
	Если ПравилаРегистрацииИзФайла = Неопределено Тогда
		ПравилаРегистрацииИзФайла = Запись.ПравилаРегистрацииИзФайла;
	КонецЕсли;
	
	Если ЕстьПравилаКонвертации = Неопределено Тогда
		ЕстьПравилаКонвертации = Запись.ЕстьПравилаКонвертации;
	КонецЕсли;
	
	Если ПравилаРегистрацииИзФайла Тогда
		Разрешения.Добавить(МодульРаботаВБезопасномРежиме.РазрешениеНаИспользованиеПривилегированногоРежима());
	КонецЕсли;
	
	Если ЕстьПравилаКонвертации Тогда
		
		Если Не Запись.РежимОтладки Тогда
			// Запрос на персональный профиль не требуется.
		Иначе
			
			Если Не ПравилаРегистрацииИзФайла Тогда
				Разрешения.Добавить(МодульРаботаВБезопасномРежиме.РазрешениеНаИспользованиеПривилегированногоРежима());
			КонецЕсли;
			
			Если Запись.РежимОтладки Тогда
				
				Если Запись.РежимОтладкиВыгрузки Тогда
					
					СтруктураИмениФайла = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(Запись.ИмяФайлаОбработкиДляОтладкиВыгрузки);
					Разрешения.Добавить(МодульРаботаВБезопасномРежиме.РазрешениеНаИспользованиеКаталогаФайловойСистемы(
					СтруктураИмениФайла.Путь, Истина, Ложь));
					
				КонецЕсли;
				
				Если Запись.РежимОтладкиЗагрузки Тогда
					
					СтруктураИмениФайла = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(Запись.ИмяФайлаОбработкиДляОтладкиВыгрузки);
					Разрешения.Добавить(МодульРаботаВБезопасномРежиме.РазрешениеНаИспользованиеКаталогаФайловойСистемы(
					СтруктураИмениФайла.Путь, Истина, Ложь));
					
				КонецЕсли;
				
				Если Запись.РежимПротоколированияОбменаДанными Тогда
					
					СтруктураИмениФайла = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(Запись.ИмяФайлаОбработкиДляОтладкиВыгрузки);
					Разрешения.Добавить(МодульРаботаВБезопасномРежиме.РазрешениеНаИспользованиеКаталогаФайловойСистемы(
					СтруктураИмениФайла.Путь, Истина, Истина));
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	ИдентификаторПланаОбмена = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(Метаданные.ПланыОбмена[Запись.ИмяПланаОбмена]);
	
	МодульРаботаВБезопасномРежимеСлужебный = ОбщегоНазначения.ОбщийМодуль("РаботаВБезопасномРежимеСлужебный");
	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ЗапросыРазрешений,
		МодульРаботаВБезопасномРежимеСлужебный.ЗапросРазрешенийДляВнешнегоМодуля(ИдентификаторПланаОбмена, Разрешения));
	
КонецПроцедуры

#КонецОбласти

#КонецЕсли

